package com.xxx.blog.controller;

import com.github.pagehelper.PageInfo;
import com.xxx.base.controller.MinIoController;
import com.xxx.base.utils.R;
import com.xxx.blog.domain.Article;
import com.xxx.blog.query.ArticleQuery;
import com.xxx.blog.service.IArticleService;
import com.xxx.blog.vo.ArchiveVo;
import com.xxx.system.annotation.PreAuthorize;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.errors.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;

/**
 * @author BoWei Wang
 * @date 2025/8/5
 */

@RestController
@RequestMapping("/article")
@Api(tags = "文章接口类")
public class ArticleController {
    @Autowired
    private IArticleService articleService;

    private static final String ACCESSKEY = "minioadmin";
    private static final String SECREKEY = "minioadmin";
    private static final String ADDRESS = "http://localhost:9000";
    private static final String BUCKETNAME = "testbucket";
    @GetMapping
    @ApiOperation("查询所有文章")
    public R<List<Article>> findAll() {
        return R.ok(articleService.findAll());
    }

    @GetMapping("/{id}")
    @ApiOperation("查询单个文章")
    @PreAuthorize(name="查询一篇文章",sn="article:getOne")
    public R<Article> findOne(@PathVariable Long id) {
        return R.ok(articleService.findOne(id));
    }

    @PostMapping
    @ApiOperation("分页条件查询文章")
    public PageInfo<Article> queryPage(@RequestBody ArticleQuery articleQuery) {
        List<Article> articles = articleService.queryPage(articleQuery);
        return new PageInfo<Article>(articles);
    }

    @PostMapping("/add")
    @ApiOperation("添加文章")
    @PreAuthorize(name = "新增文章",sn = "article:add")
    public R<Void> addArticle(@RequestBody Article article) {
        articleService.addArticle(article);
        return R.ok();
    }

    @PutMapping
    @ApiOperation("新增修改文章")
    public R<Void> addOrUpdateArticle(@ModelAttribute Article article) {
        try {

            if (article.getFile() != null && !article.getFile().isEmpty()) {
                String fileName = upload(article.getFile());
                String articlePic = "http://localhost:9000/testbucket/" + fileName;
                article.setArticlePic(articlePic);
            }

            if (article.getId() == null) {
                articleService.addArticle(article);
            } else {
                articleService.updateArticle(article);
            }

        } catch (Exception e) {
            e.printStackTrace();
            return R.fail("文章已存在!");
        }
        return R.ok();
    }

    private String upload(MultipartFile file) {
        try {
            // 构建一个Minio客户端
            MinioClient minioClient = MinioClient.builder()
                    //创建容器时指定的账号
                    .credentials(ArticleController.ACCESSKEY, ArticleController.SECREKEY)
                    //上传地址
                    .endpoint(ArticleController.ADDRESS).build();

            //处理文件名  abc.png
            String oName = file.getOriginalFilename();

            String fileName = System.currentTimeMillis()+oName.substring(oName.lastIndexOf("."));

            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .object(fileName)	//文件名
                    .bucket(ArticleController.BUCKETNAME)  //存储目录名
                    .stream(file.getInputStream(), file.getSize(), -1).build(); //文件流，以及大小，-1代表不分片

            //客户端执行上传
            minioClient.putObject(putObjectArgs);//核心代码putObject

            return fileName;//后端接口上传成功响应包装文件名作为数据进行返回给前端!
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ErrorResponseException e) {
            throw new RuntimeException(e);
        } catch (InsufficientDataException e) {
            throw new RuntimeException(e);
        } catch (InternalException e) {
            throw new RuntimeException(e);
        } catch (InvalidBucketNameException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (InvalidResponseException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (ServerException e) {
            throw new RuntimeException(e);
        } catch (XmlParserException e) {
            throw new RuntimeException(e);
        }

    }

    @DeleteMapping("/{id}")
    @ApiOperation("删除文章")
    @PreAuthorize(name = "删除一篇文章",sn = "article:delete")
    public R<Void> deleteArticle(@PathVariable Long id) {
        try {
            articleService.deleteArticle(id);
        } catch (Exception e) {
            e.printStackTrace();
            return R.fail();
        }
        return R.ok();
    }

    @PatchMapping
    @ApiOperation("批量删除文章")
    public R<Void> batchDeleteArticles(@RequestBody Long[] ids) {
        try {
            articleService.batchDeleteArticles(ids);
        } catch (Exception e) {
            e.printStackTrace();
            return R.fail();
        }
        return R.ok();
    }

    @GetMapping("/archive")
    @ApiOperation("文章归档")
    public R<List<ArchiveVo>> archive() {
        return R.ok(articleService.archive());
    }

    @GetMapping("/relate/{id}")
    @ApiOperation("根据id查询相关文章")
    public R<List<Article>> getRelate(@PathVariable("id") Long id) {
        return R.ok(articleService.getRelate(id));
    }

    /*
    * 根据年月查询文章
    * */
    @GetMapping("/archiveDetail/{yearMonth}")
    @ApiOperation("根据年月查询文章")
    public R<List<Article>> archiveDetail(@PathVariable("yearMonth") String yearMonth) {
        return R.ok(articleService.archiveDetail(yearMonth));
    }
}
